//
// A Simple Game Engine
//
// Copyright 2009 CG & CAD Institute, Tsinghua University.
// All rights reserved.
//

#include "sprite.h"

// C++ headers
//#include <iostream>

// C headers
//#include <stdio.h>

// User headers
//#include "my_header.h"

namespace engine
{

Sprite::Sprite(std::string fileName, BOUNDSACTION boundsAction)
{
    LoadImage(fileName);
    _boundsAction = boundsAction;
}

Sprite::Sprite(std::string fileName, UNIT8 r, UNIT8 g, UNIT8 b, BOUNDSACTION boundsAction)
{
    LoadImage(fileName);
    _boundsAction = boundsAction;

    if( _surface != NULL )
        SDL_SetColorKey( _surface, SDL_SRCCOLORKEY, SDL_MapRGB( _surface->format, r, g, b ) );
}

Sprite::~Sprite(void)
{
    SDL_FreeSurface(_surface);
}

void Sprite::LoadImage(std::string fileName)
{
    SDL_Surface* loadedImage = NULL;
    loadedImage = IMG_Load( fileName.c_str() );

    if( loadedImage != NULL )
    {
        _surface = SDL_DisplayFormat( loadedImage );
        SDL_FreeSurface( loadedImage );

        _collision.w = _surface->w;
        _collision.h = _surface->h;
    }

}

void Sprite::Draw(SDL_Surface* destination)
{
    SDL_Rect offset;
    offset.x = _position.x;
    offset.y = _position.y;
    SDL_BlitSurface( _surface, NULL, destination, &offset );
}

void Sprite::Update()
{
    Point newPos;
    newPos.x = _position.x + _velocity.x;
    newPos.y = _position.y + _velocity.y;

    if (_boundsAction == BA_WRAP)
    {
        if (newPos.x + _surface->w < _bound.x)
            newPos.x = _bound.x + _bound.w;
        else if (newPos.x > _bound.x + _bound.w)
            newPos.x = _bound.x - _surface->w;
        
        if (newPos.y + _surface->h < _bound.y)
            newPos.y = _bound.y + _bound.h;
        else if (newPos.y > _bound.y + _bound.h)
            newPos.y = _bound.y - _surface->h;
    }
    else if (_boundsAction == BA_WRAP)
    {
    }
    else if (_boundsAction == BA_DIE)
    {
    }
    else
    {
        if (newPos.x < _bound.x)
        {
            newPos.x = _bound.x;
            //SetVelocity(0, 0);
        }
        else if (newPos.x > _bound.x + _bound.w - _surface->w)
        {
            newPos.x = _bound.x + _bound.w - _surface->w;
            //SetVelocity(0, 0);
        }

        if (newPos.y < _bound.y)
        {
            newPos.y = _bound.y;
            //SetVelocity(0, 0);
        }
        else if (newPos.y > _bound.y + _bound.h - _surface->h)
        {
            newPos.y = _bound.y + _bound.h - _surface->h;
            //SetVelocity(0, 0);
        }
    }

    SetPosition(newPos.x, newPos.y);
}

void Sprite::SetPosition(int x, int y)
{
    _position.x = x;
    _position.y = y;
    _collision.x = x;
    _collision.y = y;
}

Point Sprite::GetPosition()
{
    return _position;
}

void Sprite::SetVelocity(int xVel, int yVel)
{
    _velocity.x = xVel;
    _velocity.y = yVel;
}

Point Sprite::GetVelocity()
{
    return _velocity;
}

void Sprite::SetBound(SDL_Rect bound)
{
    _bound = bound;
}

SDL_Rect Sprite::GetBound()
{
    return _bound;
}

void Sprite::SetCollision(SDL_Rect collision)
{
    _collision = collision;
}

SDL_Rect Sprite::GetCollision()
{
    return _collision;
}

bool Sprite::IsPointInside(int x, int y)
{
    return x >= _collision.x && x <= _collision.x + _collision.w &&
           y >= _collision.y && y <= _collision.y + _collision.h;
}

bool Sprite::TestCollision(Sprite* testSprite)
{
    SDL_Rect testCollision = testSprite->GetCollision();
    return _collision.x <= testCollision.x + testCollision.w &&
           testCollision.x <= _collision.x + _collision.w    &&
           _collision.y <= testCollision.y + testCollision.h &&
           testCollision.y <= _collision.y + _collision.h;
}

} // namespace engine
